package com.cygsunri.charge.api;


import com.alibaba.fastjson.JSON;
import com.cygsunri.common.constant.DataName;
import com.cygsunri.common.constant.DeviceType;
import com.cygsunri.common.entity.DeviceInfo;
import com.cygsunri.common.service.CommonDataService;
import com.cygsunri.measurement.calculate.AbstractComplexEndureCalculateService;
import com.cygsunri.measurement.entity.Flag;
import com.cygsunri.measurement.entity.MeasurementValue;
import com.cygsunri.scada.base.BasePSR;
import com.cygsunri.scada.service.ScadaPSRService;
import com.cygsunri.util.DateUtil;
import com.cygsunri.util.TimeUtil;
import com.github.abel533.echarts.Option;
import com.github.abel533.echarts.axis.CategoryAxis;
import com.github.abel533.echarts.series.Bar;
import com.github.abel533.echarts.series.Line;
import com.google.common.collect.Maps;
import org.apache.commons.lang3.tuple.ImmutablePair;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * 充电桩页api
 */
@RestController
@RequestMapping("/api/charge")
public class ChargeController {
    @Value("${corsair.yc.step}")
    private Integer ycStep;

    @Autowired
    private CommonDataService commonDataService;

    @Autowired
    private ScadaPSRService scadaPSRService;

    @Autowired
    private AbstractComplexEndureCalculateService abstractComplexEndureCalculateService;

    /**
     * 充电桩整体使用率
     *
     * @param id 充电桩PSRID
     */
    @RequestMapping(value = "/charts/brief/substations/{id}", method = RequestMethod.GET)
    public ResponseEntity<List<MeasurementValue>> brief(@PathVariable("id") String id) {
        List<MeasurementValue> measurementValues = new ArrayList<>();
        BasePSR basePSR = scadaPSRService.getDeviceByPsrId(id);
        if (basePSR != null) {
            MeasurementValue p = commonDataService.getValueFillDisPlay(basePSR.getId(), DataName.TOTAL_ACTIVE_POWER);
            MeasurementValue efficiency = commonDataService.getValueFillDisPlay(basePSR.getId(), DataName.UTILIZATION);

            measurementValues.add(p);
            measurementValues.add(efficiency);
        }
        return new ResponseEntity<>(measurementValues, HttpStatus.OK);
    }

    /**
     * 充电桩每日充电量
     *
     * @param id   充电桩PSRID
     * @param from 开始时间
     * @param to   结束时间
     */
    @RequestMapping(value = "/charts/statistics/kwh/substations/{id}/{from}/{to}", method = RequestMethod.GET)
    public ResponseEntity<String> statisticsKwh(@PathVariable("id") String id, @PathVariable("from") String from, @PathVariable("to") String to) {
        Option option = new Option();
        CategoryAxis categoryAxis = new CategoryAxis();
        option.xAxis(categoryAxis);

        BasePSR substation = scadaPSRService.getDeviceByPsrId(id);
        if (substation == null) {
            return new ResponseEntity<>(JSON.toJSONString(option), HttpStatus.NOT_FOUND);
        }

        Bar dcChargeGun1 = new Bar("直流充电桩枪1");
        option.series(dcChargeGun1);

        Bar dcChargeGun2 = new Bar("直流充电桩枪2");
        option.series(dcChargeGun2);

        Bar acCharge1Gun1 = new Bar("交流充电桩1");
        option.series(acCharge1Gun1);

        Bar acCharge2Gun1 = new Bar("交流充电桩2");
        option.series(acCharge2Gun1);

        List<String> dates = DateUtil.getDays(from, to);
        List<BasePSR> dcCharges = scadaPSRService.getDeviceOfSubstationByType(id, DeviceType.DC_CHARGING.getKey());
        for (BasePSR dcCharge : dcCharges) {
            for (String date : dates) {
                MeasurementValue gun1DayCharge = commonDataService.getValue(dcCharge.getId(), DataName.GUN1_TOTAL_CHARGE, TimeUtil.toMilliSeconds(date), Flag.DAY_DIFF);
                dcChargeGun1.data(gun1DayCharge.isInValid() ? "-" : gun1DayCharge.getData());

                MeasurementValue gun2DayCharge = commonDataService.getValue(dcCharge.getId(), DataName.GUN2_TOTAL_CHARGE, TimeUtil.toMilliSeconds(date), Flag.DAY_DIFF);
                dcChargeGun2.data(gun2DayCharge.isInValid() ? "-" : gun2DayCharge.getData());
            }
        }

        List<BasePSR> acCharges = scadaPSRService.getDeviceOfSubstationByType(id, DeviceType.AC_CHARGING.getKey());

        BasePSR acCharges1 = acCharges.get(0);
        for (String date : dates) {
            MeasurementValue dayCharge = commonDataService.getValue(acCharges1.getId(), DataName.GUN1_TOTAL_CHARGE, TimeUtil.toMilliSeconds(date), Flag.DAY_DIFF);
            acCharge1Gun1.data(dayCharge.isInValid() ? "-" : dayCharge.getData());
        }

        BasePSR acCharges2 = acCharges.get(1);
        for (String date : dates) {
            MeasurementValue dayCharge = commonDataService.getValue(acCharges2.getId(), DataName.GUN1_TOTAL_CHARGE, TimeUtil.toMilliSeconds(date), Flag.DAY_DIFF);
            acCharge2Gun1.data(dayCharge.isInValid() ? "-" : dayCharge.getData());
        }

        for (String date : dates) {
            categoryAxis.data(date);
        }
        return new ResponseEntity<>(JSON.toJSONString(option), HttpStatus.OK);
    }

    /**
     * 充电桩运行状态
     *
     * @param id 充电桩PSRID
     */
    @RequestMapping(value = "/statistics/substations/{id}/charges", method = RequestMethod.GET)
    public ResponseEntity<List<DeviceInfo>> invertersInfo(@PathVariable("id") String id) {
        List<DeviceInfo> deviceInfoList = new ArrayList<>();
        List<BasePSR> acCharges = scadaPSRService.getDeviceOfSubstationByType(id, DeviceType.AC_CHARGING.getKey());
        for (BasePSR acCharge : acCharges) {
            ImmutablePair<String, String> pair = abstractComplexEndureCalculateService.getDeviceStatusPair(acCharge.getId());
            DeviceInfo deviceInfo = new DeviceInfo()
                    .setPsrID(acCharge.getId())
                    .setName(acCharge.getName())
                    .setType(DeviceType.AC_CHARGING.getName())
                    .setStatus(pair == null ? null : pair.getRight());

            if(Objects.equals(deviceInfo.getStatus(), "RUNNING")) {
                MeasurementValue chargeGun1Status = commonDataService.getValue(acCharge.getId(), DataName.GUN1_STATUS);
                if (chargeGun1Status.isInValid()) {
                    deviceInfo.setStatus("UNKNOWN");
                }
                switch (chargeGun1Status.getData().intValue()) {
                    case 0:
                        deviceInfo.setStatus("STANDBY");
                        break;
                    case 1:
                        deviceInfo.setStatus("RUNNING");
                        break;
                    default:
                        deviceInfo.setStatus("FAULT");
                        break;
                }
            }

            List<Map<String, String>> list = new ArrayList<>();

            MeasurementValue gun1OutPower = commonDataService.getValue(acCharge.getId(), DataName.GUN1_OUT_POWER);
            MeasurementValue gun1DayCharge = commonDataService.getValue(acCharge.getId(), DataName.GUN1_CHARGE);

            Map<String, String> m1 = Maps.newHashMap();
            m1.put("name", DataName.GUN1_OUT_POWER);
            m1.put("data", gun1OutPower.isInValid() ? "-" : String.valueOf(gun1OutPower.getData()));
            list.add(m1);

            Map<String, String> m2 = Maps.newHashMap();
            m2.put("name", DataName.GUN1_CHARGE);
            m2.put("data", gun1DayCharge.isInValid() ? "-" : String.valueOf(gun1DayCharge.getData()));
            list.add(m2);

            deviceInfo.setExtra(list);
            deviceInfoList.add(deviceInfo);
        }

        List<BasePSR> dcCharges = scadaPSRService.getDeviceOfSubstationByType(id, DeviceType.DC_CHARGING.getKey());
        for (BasePSR dcCharge : dcCharges) {
            ImmutablePair<String, String> pair = abstractComplexEndureCalculateService.getDeviceStatusPair(dcCharge.getId());
            DeviceInfo deviceInfo1 = new DeviceInfo()
                    .setPsrID(dcCharge.getId())
                    .setName(dcCharge.getName() + "枪1")
                    .setType(DeviceType.DC_CHARGING.getName())
                    .setStatus(pair == null ? null : pair.getRight());

            if(Objects.equals(deviceInfo1.getStatus(), "RUNNING")) {
                MeasurementValue chargeGun1Status = commonDataService.getValue(dcCharge.getId(), DataName.GUN1_STATUS);
                if (chargeGun1Status.isInValid()) {
                    deviceInfo1.setStatus("UNKNOWN");
                }
                switch (chargeGun1Status.getData().intValue()) {
                    case 0:
                        deviceInfo1.setStatus("STANDBY");
                        break;
                    case 1:
                        deviceInfo1.setStatus("RUNNING");
                        break;
                    default:
                        deviceInfo1.setStatus("FAULT");
                        break;
                }
            }

            DeviceInfo deviceInfo2 = new DeviceInfo()
                    .setPsrID(dcCharge.getId())
                    .setName(dcCharge.getName() + "枪2")
                    .setType(DeviceType.DC_CHARGING.getName())
                    .setStatus(pair == null ? null : pair.getRight());

            if(Objects.equals(deviceInfo2.getStatus(), "RUNNING")) {
                MeasurementValue chargeGun1Status = commonDataService.getValue(dcCharge.getId(), DataName.GUN2_STATUS);
                if (chargeGun1Status.isInValid()) {
                    deviceInfo2.setStatus("UNKNOWN");
                }
                switch (chargeGun1Status.getData().intValue()) {
                    case 0:
                        deviceInfo2.setStatus("STANDBY");
                        break;
                    case 1:
                        deviceInfo2.setStatus("RUNNING");
                        break;
                    default:
                        deviceInfo2.setStatus("FAULT");
                        break;
                }
            }

            List<Map<String, String>> list1 = new ArrayList<>();
            List<Map<String, String>> list2 = new ArrayList<>();

            MeasurementValue gun1OutPower = commonDataService.getValue(dcCharge.getId(), DataName.GUN1_OUT_POWER);
            MeasurementValue gun2OutPower = commonDataService.getValue(dcCharge.getId(), DataName.GUN2_OUT_POWER);
            MeasurementValue gun1DayCharge = commonDataService.getValue(dcCharge.getId(), DataName.GUN1_CHARGE);
            MeasurementValue gun2DayCharge = commonDataService.getValue(dcCharge.getId(), DataName.GUN2_CHARGE);

            Map<String, String> m1 = Maps.newHashMap();
            m1.put("name", DataName.GUN1_OUT_POWER);
            m1.put("data", gun1OutPower.isInValid() ? "-" : String.valueOf(gun1OutPower.getData()));
            list1.add(m1);

            Map<String, String> m2 = Maps.newHashMap();
            m2.put("name", DataName.GUN2_OUT_POWER);
            m2.put("data", gun1OutPower.isInValid() ? "-" : String.valueOf(gun2OutPower.getData()));
            list2.add(m2);

            Map<String, String> m3 = Maps.newHashMap();
            m3.put("name", DataName.GUN1_CHARGE);
            m3.put("data", gun1DayCharge.isInValid() ? "-" : String.valueOf(gun1DayCharge.getData()));
            list1.add(m3);

            Map<String, String> m4 = Maps.newHashMap();
            m4.put("name", DataName.GUN2_CHARGE);
            m4.put("data", gun1DayCharge.isInValid() ? "-" : String.valueOf(gun2DayCharge.getData()));
            list2.add(m4);

            deviceInfo1.setExtra(list1);
            deviceInfo2.setExtra(list2);
            deviceInfoList.add(deviceInfo1);
            deviceInfoList.add(deviceInfo2);
        }
        return new ResponseEntity<>(deviceInfoList, HttpStatus.OK);
    }

    /**
     * 充电桩功率曲线
     *
     * @param id   充电桩PSRID
     * @param date 日期 2021-04-22
     */
    @RequestMapping(value = "/charts/power/substations/{id}/dates/{date}", method = RequestMethod.GET)
    public ResponseEntity<String> power(@PathVariable("id") String id, @PathVariable("date") String date) {
        Option option = new Option();
        CategoryAxis categoryAxis = new CategoryAxis();
        option.xAxis(categoryAxis);

        Line dcChargeGun1Line = new Line("直流充电桩枪1");
        option.series(dcChargeGun1Line);

        Line dcChargeGun2Line = new Line("直流充电桩枪2");
        option.series(dcChargeGun2Line);

        Line acCharge1Gun1Line = new Line("交流充电桩1");
        option.series(acCharge1Gun1Line);

        Line acCharge2Gun1Line = new Line("交流充电桩2");
        option.series(acCharge2Gun1Line);

        List<BasePSR> dcCharges = scadaPSRService.getDeviceOfSubstationByType(id, DeviceType.DC_CHARGING.getKey());
        for (BasePSR dcCharge : dcCharges) {
            List<MeasurementValue> dcChargeGun1Values = commonDataService.getHistoryValue(dcCharge.getId(), DataName.GUN1_OUT_POWER, date.trim() + " 00:00", date.trim() + " 24:00", ycStep, 2, false);
            if (!dcChargeGun1Values.isEmpty()) {
                for (MeasurementValue today : dcChargeGun1Values) {
                    if (categoryAxis.getData() == null || categoryAxis.getData().size() < 288 ) {
                        categoryAxis.data(today.getTime());
                    }
                    dcChargeGun1Line.data(today.isInValid() ? "-" : today.getData());
                }
            }

            List<MeasurementValue> dcChargeGun2Values = commonDataService.getHistoryValue(dcCharge.getId(), DataName.GUN2_OUT_POWER, date.trim() + " 00:00", date.trim() + " 24:00", ycStep, 2, false);
            if (!dcChargeGun2Values.isEmpty()) {
                for (MeasurementValue today : dcChargeGun2Values) {
                    if (categoryAxis.getData() == null || categoryAxis.getData().size() < 288 ) {
                        categoryAxis.data(today.getTime());
                    }
                    dcChargeGun2Line.data(today.isInValid() ? "-" : today.getData());
                }
            }
        }

        List<BasePSR> acCharges = scadaPSRService.getDeviceOfSubstationByType(id, DeviceType.AC_CHARGING.getKey());

        if (!acCharges.isEmpty()) {

            BasePSR acCharges1 = acCharges.get(0);
            List<MeasurementValue> acCharge1Gun1Values = commonDataService.getHistoryValue(acCharges1.getId(), DataName.GUN1_OUT_POWER, date.trim() + " 00:00", date.trim() + " 24:00", ycStep, 2, false);

            if (!acCharge1Gun1Values.isEmpty()) {
                for (MeasurementValue today : acCharge1Gun1Values) {
                    if (categoryAxis.getData() == null || categoryAxis.getData().size() < 288) {
                        categoryAxis.data(today.getTime());
                    }
                    acCharge1Gun1Line.data(today.isInValid() ? "-" : today.getData());
                }
            }

            BasePSR acCharges2 = acCharges.get(1);
            List<MeasurementValue> acCharge2Gun1Values = commonDataService.getHistoryValue(acCharges2.getId(), DataName.GUN1_OUT_POWER, date.trim() + " 00:00", date.trim() + " 24:00", ycStep, 2, false);

            if (!acCharge2Gun1Values.isEmpty()) {
                for (MeasurementValue today : acCharge2Gun1Values) {
                    if (categoryAxis.getData() == null || categoryAxis.getData().size() < 288) {
                        categoryAxis.data(today.getTime());
                    }
                    acCharge2Gun1Line.data(today.isInValid() ? "-" : today.getData());
                }
            }
        }

        return new ResponseEntity<>(JSON.toJSONString(option), HttpStatus.OK);
    }


}
